#include <stdint.h>
#include <string.h>
#include "value.h"
#include "packet.h"
#include "mqtt.h"

static void _set_datetime(const time_t *time, datetime_t *dt) {
    struct tm _tm;

    localtime_r(time, &_tm);
    dt->sec = _tm.tm_sec;
    dt->min = _tm.tm_min;
    dt->hour = _tm.tm_hour;
    dt->day = _tm.tm_mday;
    dt->mon = _tm.tm_mon + 1;
    dt->year = _tm.tm_year - 100;
}

//data_bytes = flag(1) + value(1|2|4|8|16) + [timestamp(4)] + [quality(1)]
static void _init_header(mqtt_handler_t *handler, hdb_header_t *head, device_t *device) {
    bzero(head, sizeof(hdb_header_t));
    head->dev_id = device->super.id;
    head->n_tags = 0;
}

int publish_packet(mqtt_handler_t *handler, device_t *device) {
    int i, j;
    segment_e segments[] = {seg_do, seg_di, seg_ao, seg_ai};

    char payload[1024 * 4]; //4k
    hdb_header_t *head = (hdb_header_t *) payload;
    char *s = payload + sizeof(hdb_header_t);
    char *e = payload + sizeof(payload) - (1 + 2 + 8 + 4);

    char *p = s;
    _init_header(handler, head, device);
    for (i = 0; i < sizeof(segments) / sizeof(segments[0]); ++i) {
        segment_e segment = segments[i];
        vector_t *tag_list = &device->_product->thing_model[segment];
        vector_t *val_list = &device->thing_value[segment];

        for (j = 0; j < vector_size(val_list); ++j) {
            thing_model_t *tag = vector_get(tag_list, j);
            value_t *value = vector_get(val_list, j);

            if (value->_changed) {
                value->_changed = false;

                tag_header_t tag_header;
                tag_header.value_len = sizeof(value->value);
                tag_header.is_signed = true;
                tag_header.is_floating = true;
                tag_header.has_timestamp = false;
                tag_header.has_quality = (0 != value->quality);
                tag_header.quality = value->quality;
                tag_header.tag_id = thing_model_tag_id(tag);
                memcpy(p, &tag_header, sizeof(tag_header));
                p += sizeof(tag_header);

                memcpy(p, &value->value, sizeof(value->value));
                p += sizeof(value->value);

                if (tag_header.has_timestamp) {
                    datetime_t *dt = (datetime_t *) p;
                    _set_datetime(&value->timestamp, dt);
                    p += sizeof(datetime_t);
                }
            }

            if (p >= e) {
                int rc = mqtt_write(handler, "/user/packet", payload, p - payload);
                if (rc < 0) {
                    return rc;
                }

                p = s;
                _init_header(handler, head, device);
            }
        }
    }

    if (p > s) {
        return mqtt_write(handler, "/user/packet", payload, p - payload);
    }

    return 0;
}
